package com.moorror.cola.strategy.plugin.utils;

import com.google.common.collect.Maps;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
import com.intellij.psi.search.GlobalSearchScope;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;


import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @Author jiyanghuang
 * @Date 2023/7/15 17:10
 */
public class AnnotationFindUtils {

    /**
     *
     * @param annString
     * @param prefixPackage
     * @param project
     * @return
     */
    public static Map<Module, List<PsiClass>> fetchPsiClassByAnnotation(String annString, String prefixPackage, Project project) {

        Map<Module, List<PsiClass>> modulePsiClass = Maps.newConcurrentMap();
        Module[] modules = ModuleManager.getInstance(project).getModules();
        for (Module module : modules) {
            GlobalSearchScope moduleScope = fetchModuleScope(module);
            Collection<PsiAnnotation> pathList = JavaAnnotationIndex.getInstance().get(
                    annString,
                    project,
                    moduleScope
            );
            for (PsiAnnotation psiAnnotation : pathList) {
                PsiElement psiElement = psiAnnotation.getParent();
                if (psiAnnotation.getParent() instanceof PsiModifierList) {
                    PsiModifierList psiModifierList = (PsiModifierList) psiAnnotation.getParent();
                    psiElement = psiModifierList.getParent();
                }

                if (!(psiElement instanceof PsiClass)) {
                    continue;
                }

                List<PsiClass> allPsiClass = modulePsiClass.get(module);
                if (null == allPsiClass) {
                    allPsiClass = Lists.newArrayList();
                    modulePsiClass.put(module, allPsiClass);
                }

                PsiClass psiClass = (PsiClass) psiElement;
                if (StringUtils.isBlank(prefixPackage)) {
                    allPsiClass.add(psiClass);
                } else if (psiClass.getQualifiedName().startsWith(prefixPackage)) {
                    allPsiClass.add(psiClass);
                }
            }
        }
        return modulePsiClass;
    }

    /**
     *
     * @param module
     * @return
     */
    public static GlobalSearchScope fetchModuleScope(@NotNull Module module) {
        return fetchModuleScope(module, true);
    }

    /**
     * @param module
     * @param hasLibrary
     * @return
     */
    public static GlobalSearchScope fetchModuleScope(@NotNull Module module, boolean hasLibrary) {
        if (hasLibrary) {
            return module.getModuleWithLibrariesScope();
        }
        return module.getModuleScope();
    }
}
